#include <commands/client/c_request_terrain_tile.h>
#include <commands/server/s_send_terrain_tile.h>
#include <app/states/connectionState.h>
#include <cache/cacheKeysFactory.h>
#include <cache/terrainCacheKey.h>

REGISTER_COMMAND(CLIENT_REQUEST_TERRAIN_TILE, c_request_terrain_tile)

c_request_terrain_tile::c_request_terrain_tile() : command(0, NULL) {
  x = 0;
  y = 0;
  level = 0;
}

c_request_terrain_tile::c_request_terrain_tile(unsigned int _type_id, streamingConnection *_connection) : command(_type_id, _connection) {
  x = 0;
  y = 0;
  level = 0;
}

#ifdef CLIENT
void 
c_request_terrain_tile::setData(int x_, int y_, int level_, boost::shared_ptr<tile> * caller_) {
  x = x_;
  y = y_;
  level = level_;
  caller = caller_;

  terrain_tile_state = GET_STATE(terrainTileState, getconnection());
}
#endif

void
c_request_terrain_tile::decode(stringstream &bytes_stream, int size) {
#ifdef SERVER

  #ifdef DEBUG_INFO
  std::cerr << "SERVER DECODE: c_request_terrain_tile" << std::endl;
  #endif

  streamingConnection *conn = getconnection();
  terrainTileState *ttstate = GET_STATE(terrainTileState, conn);

  bytes_stream >> x;
  bytes_stream >> y;
  bytes_stream >> level;

  ttstate->requestTerrainTile(x, y, level);

  terrainCacheKey *ter_cache = static_cast<terrainCacheKey *>(cacheKeysFactory::instance().createCacheKey(CACHE_KEY_TERRAIN, &conn->getSession()));
  ter_cache->init(x, y, level);

  ter_cache->load();

  s_send_terrain_tile *cmd = static_cast<s_send_terrain_tile *>(commandFactory::instance().createCommand(SERVER_SEND_TERRAIN_TILE, conn));
  int data_size = 0;
  unsigned char *data = ter_cache->getData(data_size);
  cmd->setData(x, y, level, data, data_size);
  cmd->execute();
  delete cmd;

  delete ter_cache;
  
#endif
}

void 
c_request_terrain_tile::execute() {
#ifdef CLIENT
  
  #ifdef DEBUG_INFO
  std::cerr << "CLIENT EXECUTE: c_request_terrain_tile" << std::endl;
  #endif

  terrain_tile_state->requestTerrainTile(x, y, level, caller);

  unsigned int *id = new unsigned int[1];
  unsigned int *total_size = new unsigned int[1];
  unsigned int data_size;

  total_size[0] = sizeof(unsigned int); // total size itself

  id[0] = getTypeId();
  total_size[0] += sizeof(unsigned int); // id size

  stringstream bytes(ios::out | ios::in | ios::binary);
   bytes << x << endl;
   bytes << y << endl;
   bytes << level << endl;
   bytes.seekg(0, ios::end);
  data_size = bytes.tellg();

  unsigned char *data = new unsigned char[data_size];
  bytes.seekg(0, ios::beg);
  bytes.read((char *) data, data_size);

  total_size[0] += data_size;
  
  sendBytes(total_size, sizeof(unsigned int));
  sendBytes(id, sizeof(unsigned int));

  bytes.seekg(0, ios::beg);
  sendBytes(data, data_size);

#endif
}
